//
//  tdl/mem/hash_fun.h
//  Created by tommy on 13/01/17.
//

#ifndef tdl_mem_hashfun_h
#define tdl_mem_hashfun_h

#include <sys/types.h>
#include <ext/hash_fun.h>
#include <cmath>
using namespace tdl;

namespace tdl{
////////////////////////////////////
bool is_prime(uint32_t n)
{
	double s = sqrt(n);
	for(uint32_t i = 2; i <= s; ++i)
		if(n % i == 0)
			return false;
	return true;
}

const size_t DEFAULT_HASH = 1543;

template <typename T>
struct hash { };


template <>
struct hash<int64_t>
{
	int64_t operator()(int64_t x, uint32_t h = DEFAULT_HASH) const
	{ return x % h; }
};
	
template <>
struct hash<uint64_t>
{
	uint64_t operator()(uint64_t x, uint32_t h = DEFAULT_HASH) const
	{ return x % h; }
};

template <>
struct hash<int32_t>
{
	int32_t operator()(int32_t x, uint32_t h = DEFAULT_HASH) const
	{ return x % h; }
};

template <>
struct hash<uint32_t>
{
	uint32_t operator()(uint32_t x, uint32_t h = DEFAULT_HASH) const
	{ return x % h; }
};

template <>
struct hash<int16_t>
{
	int16_t operator()(int16_t x, uint32_t h = DEFAULT_HASH) const
	{ return x % h; }
};
	
template <>
struct hash<uint16_t>
{
	uint16_t operator()(uint16_t x, uint32_t h = DEFAULT_HASH) const
	{ return x % h; }
};

template <>
struct hash<std::string>
{
	size_t operator()(const std::string& s, uint32_t h = DEFAULT_HASH) const
	{ return __gnu_cxx::__stl_hash_string(s.c_str()); }
};
/*
template <>
struct hash<tdl::ip_end>
{
	size_t
	operator()(tdl::ip_end ip, size_t h = DEFAULT_HASH) const
	{ return ip.toInt() % h; }
};
*/
template <typename T>
struct chash { };

template <>
struct chash<std::string>
{
	size_t operator()(const std::string &key) const
	{
		const char *ptr= key.c_str();
		size_t key_length = key.length();
		uint32_t value= 0;
		while (key_length--) 
		{
			value += *ptr++;
			value += (value << 10);
			value ^= (value >> 6);
		}
		value += (value << 3);
		value ^= (value >> 11);
		value += (value << 15); 

		return value;
	}
};

/////////////////////////////
}	// end of namespace
#endif

